/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/head.h"
#include "log_file.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace xos_log
{

    log_file::log_file()
    {
        init_data();
    }

    log_file::~log_file()
    {
    }

    ///////////////////////////////////////////////////////////////////////////////////
    // i_log_file方法

    // 
    // 设置日志路径
    // 
    int log_file::set_log_file_path( const char * lpszLogPath )
    {
        int ret = 0;
        m_path = lpszLogPath;
        ret = create_log_path();
        return ret;
    }

    int log_file::set_log_file_name( const char * lpszFile )
    {
        int ret = 0;
        m_file = lpszFile;
        ret = fmt_file_name();
        return ret;
    }

    int log_file::set_buf_num_to_flush( int nBufNum )
    {
        int ret = 0;
        m_nBufNumToFlush = nBufNum;
        return ret;
    }

    // 
    // 输出日志
    // 
    int log_file::out_put_log( i_log_msg * pLogMsg )
    {
        int ret = 0;

        int nYear = 0, nMon = 0, nDay = 0, nHour = 0, nMinute = 0;
        bool bFlush = false;
        int nLogBufNum = 0;

        {
            pLogMsg->get_log_time( &nYear,
                &nMon,
                &nDay,
                &nHour,
                &nMinute,
                0,
                0 );
            nLogBufNum = m_pLogList->size();
        }

        if( m_nCurHour == nHour )
        {
            add_log_to_buf( pLogMsg );
            pLogMsg = 0;
            nLogBufNum = m_pLogList->size();
        }

        if( !bFlush && ( m_nCurHour != nHour ) )
        {
            printf( "hour changed : %02d - %02d\r\n", m_nCurHour, nHour );
            bFlush = true;
        }

        if( !bFlush && ( m_nCurMinute != nMinute ) )
        {
            printf( "minute changed : %02d - %02d\r\n", m_nCurMinute, nMinute );
            bFlush = true;
        }

        if( !bFlush && ( nLogBufNum >= m_nBufNumToFlush ) )
        {
            printf( "log buf num enough : %d\r\n", nLogBufNum );
            bFlush = true;
        }

        if( ( bFlush ) && ( nLogBufNum > 0 ) )
        {
            printf( "need flush. %04d-%02d-%02d %02d:%02d\r\n",
                nYear,
                nMon,
                nDay,
                nHour,
                nMinute );
            flush();
        }

        if( bFlush && ( m_nCurMinute != nMinute ) )
        {
            m_nCurMinute = nMinute;
        }

        if( bFlush && ( ( m_nYear != nYear ) || ( m_nMonth != nMon ) || ( m_nDay != nDay ) || ( m_nCurHour != nHour ) ) )
        {
            m_nCurHour = nHour;
            m_nYear = nYear;
            m_nMonth = nMon;
            m_nDay = nDay;
            fmt_file_name();
        }

        if( pLogMsg )
        {
            add_log_to_buf( pLogMsg );
            pLogMsg = 0;
        }

        return ret;
    }

    int log_file::flush()
    {
        int ret = 0;

        int nLogBufNum = m_pLogList->size();
        xos::i_file * pFile = 0;

        if( ( 0 == ret ) && ( 0 == nLogBufNum ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            pFile = mgr::container()->xos()->file();
        }

        if( 0 == ret )
        {
            ret = pFile->open( m_full_file.c_str(), xos::i_file::XOS_FILE_WRITE, 0, xos::i_file::XOS_FILE_CREATE );
        }

        if( 0 == ret )
        {
            ret = pFile->set_file_pos( xos::i_file::XOS_FILE_POS_END, 0, 0 );
        }

        // 写入pBuf时确保结尾有0
        if( 0 == ret )
        {
            pFile->write( m_pLogList );
        }

        if( 0 == ret )
        {
            printf( "flush log buf num = %d\r\n", nLogBufNum );
            m_pLogList->release_all();
        }

        xos_stl::release_interface( pFile );

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int log_file::add_log_to_buf( i_log_msg * pLogMsg )
    {
        int ret = 0;
        const char * lpszLog = 0;
        int nLogLen = 0;
        lpszLog = pLogMsg->get_log_content( 0, 0, &nLogLen );
        m_pLogList->add_data( lpszLog, nLogLen, true );
        m_pLogList->add_data( "\r\n", 2, true );
        return ret;
    }

    int log_file::create_log_path()
    {
        int ret = 0;

        xos::i_dir * pDir = 0;

        if( ( 0 == ret ) && m_path.empty() )
        {
            xos_box::i_string * pStr = mgr::container()->box()->string();
            mgr::container()->misc()->get_process_path( pStr );
            m_path = pStr->get( 0, 0 );
            xos_stl::release_interface( pStr );
        }

        if( 0 == ret )
        {
            pDir = mgr::container()->xos()->dir();
        }

        if( ( 0 == ret ) && ( 0 != pDir->is_dir_exist( m_path.c_str() ) ) )
        {
            ret = pDir->create_directory( m_path.c_str() );
        }

        if( 0 == ret )
        {
            xos::i_time * pTime = mgr::container()->xos()->tm();
            pTime->get_time();
            m_nYear = pTime->get_year();
            m_nMonth = pTime->get_month();
            m_nDay = pTime->get_day();
            m_nCurHour = pTime->get_hour();
            m_nCurMinute = pTime->get_minute();
            xos_stl::release_interface( pTime );
        }

        if( 0 == ret )
        {
            fmt_file_name();
        }

        xos_stl::release_interface( pDir );

        return ret;
    }

    int log_file::fmt_file_name()
    {
        int ret = 0;

        xos_box::i_string * pFullName = mgr::container()->box()->string();
        xos_box::i_string * pName = mgr::container()->box()->string();

        if( 0 == ret )
        {
            mgr::container()->crt()->sprintf( pName, "%s_%04d-%02d-%02d-%02d.log",
                m_file.c_str(),
                m_nYear,
                m_nMonth,
                m_nDay,
                m_nCurHour );
            pFullName->set( m_path.c_str(), m_path.length() );
            mgr::container()->misc()->path_append( pFullName, pName );
        }

        if( 0 == ret )
        {
            m_full_file = pFullName->get( 0, 0 );
        }

        xos_stl::release_interface( pFullName );
        xos_stl::release_interface( pName );

        return ret;
    }

    int log_file::init_data()
    {
        int ret = 0;

        m_nBufNumToFlush = 10;
        m_pLogList = 0;

        m_full_file = "";
        m_path = "";
        m_file = "xos";

        m_nYear = 0;
        m_nMonth = 0;
        m_nDay = 0;
        m_nCurHour = 0;
        m_nCurMinute = 0;

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // for release_impl to use.
    // 

    int log_file::put_back_to_pool()
    {
        int ret = 0;
        delete this;
        return ret;
    }

    int log_file::init()
    {
        int ret = 0;
        m_pLogList = mgr::container()->box()->list();
        create_log_path();
        return ret;
    }

    int log_file::term()
    {
        int ret = 0;
        xos_stl::release_interface( m_pLogList );
        init_data();
        return ret;
    }

} // xos_log
